// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... namespace LargoCommon.Music { using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; using System.Text; using System.Xml.Serialization; using Abstract; using LargoCommon.Interfaces; /// Harmonic modality. /// /// Harmonic modality is defined by its number and appropriateness /// to harmonic GSystem. [Serializable] [XmlRoot] public sealed class HarmonicModality : BinarySchema, IHarmonic, IModalStruct { #region Fields /// String of musical symbols. private string toneSchema; #endregion #region Constructors /// Initializes a new instance of the HarmonicModality class. Serializable. public HarmonicModality() { } /// /// Initializes a new instance of the HarmonicModality class. /// /// The given system. /// Structural code. public HarmonicModality(GeneralSystem givenSystem, string structuralCode) : base(givenSystem, structuralCode) { Contract.Requires(givenSystem != null); } /// /// Initializes a new instance of the HarmonicModality class. /// /// The given system. /// Bit array. public HarmonicModality(GeneralSystem givenSystem, BitArray givenBitArray) : base(givenSystem, givenBitArray) { Contract.Requires(givenSystem != null); } /// /// Initializes a new instance of the HarmonicModality class. /// /// The given system. /// Number of modality. /// Transposition shift. public HarmonicModality(GeneralSystem givenSystem, long number, byte transposition) : base(givenSystem, BinaryNumber.Transposition(givenSystem, number, transposition)) { Contract.Requires(givenSystem != null); } /// /// Initializes a new instance of the HarmonicModality class. Serializable. /// /// Harmonic order. /// Melodic tones. /// Min Altitude. /// Properties Needed. public HarmonicModality(byte harmonicOrder, IEnumerable melodicTones, int minAltitude, bool propertiesNeeded) : base(HarmonicSystem.GetHarmonicSystem(harmonicOrder), (string)null) { Contract.Requires(harmonicOrder != 0); Contract.Requires(melodicTones != null); //// if (melodicTones == null) { return; } //// mt.Pitch.Element foreach (var mt in melodicTones) { if (mt is MusicalTone tone && tone.IsTrueTone) { byte element = (byte)((tone.Pitch.SystemAltitude - minAltitude) % harmonicOrder); this.On(element); } } this.DetermineLevel(); if (propertiesNeeded) { this.ComputeVariance(); this.ComputeBalance(); } } /// /// Initializes a new instance of the HarmonicModality class. /// /// The given system. /// Number of structure. public HarmonicModality(GeneralSystem givenSystem, long number) : base(givenSystem, number) { } /// Initializes a new instance of the HarmonicModality class. /// Binary structure. public HarmonicModality(BinaryStructure structure) : base(structure) { Contract.Requires(structure != null); } #endregion #region Interface - simple properties /// /// Gets or sets the name. /// /// /// The name. /// public string Name { get; set; } /// Gets or sets tone representation. /// Property description. [XmlAttribute] public string ToneSchema { get => this.toneSchema ?? (this.toneSchema = this.SchemaOfTones()); set => this.toneSchema = value; } /// /// Gets the name and tones. /// /// /// The name and tones. /// public string NameAndTones => this.Name + this.ToneSchema; /// /// Gets or sets the formal energy. /// /// /// The formal energy. /// public HarmonicBehavior FormalEnergy { get; set; } /// Gets inner continuity. /// Property description. public float FormalContinuity => this.Properties.ContainsKey(GenProperty.InnerContinuity) ? this.Properties[GenProperty.InnerContinuity] : 0f; /// Gets inner impulse. /// Property description. public float FormalImpulse => this.Properties.ContainsKey(GenProperty.InnerImpulse) ? this.Properties[GenProperty.InnerImpulse] : 0f; /// Gets inner heterogeneity. /// Property description. public float Heterogeneity => this.Properties.ContainsKey(GenProperty.FormalVariance) ? this.Properties[GenProperty.FormalVariance] : 0f; /// Gets inner balance. /// Property description. public float FormalBalance => this.Properties.ContainsKey(GenProperty.FormalBalance) ? this.Properties[GenProperty.FormalBalance] : 0f; /// Gets inner balance. /// Property description. [XmlIgnore] public float HarmonicModulationPower { get; private set; } #endregion #region Interface - object properties /// Gets harmonic system. /// Property description. [XmlIgnore] public HarmonicSystem HarmonicSystem { get { Contract.Ensures(Contract.Result() != null); return (HarmonicSystem)this.GSystem; } } #endregion #region Static factory methods /// /// Get New Harmonic Modality. /// /// The given system. /// Structural code. /// /// Returns value. /// public static HarmonicModality GetNewHarmonicModality(GeneralSystem givenSystem, string structuralCode) { Contract.Requires(givenSystem != null); var hm = new HarmonicModality(givenSystem, structuralCode); hm.DetermineBehavior(); return hm; } /// /// Get New Harmonic Modality. /// /// The given system. /// Bit array. /// /// Returns value. /// public static HarmonicModality GetNewHarmonicModality(GeneralSystem givenSystem, BitArray bitArray) { Contract.Requires(givenSystem != null); var hm = new HarmonicModality(givenSystem, bitArray); hm.DetermineBehavior(); return hm; } /// /// Get New Harmonic Modality. /// /// The given system. /// Structural Number. /// Given Transposition. /// /// Returns value. /// public static HarmonicModality GetNewHarmonicModality(GeneralSystem givenSystem, long number, byte givenTransposition) { Contract.Requires(givenSystem != null); var hm = new HarmonicModality(givenSystem, number, givenTransposition); hm.DetermineBehavior(); return hm; } /// /// Loads the harmonic modality. /// /// The harmonic order. /// The mod number. /// Name of the mod. /// Returns value. public static HarmonicModality LoadHarmonicModality(byte harmonicOrder, long modNumber, string modName) { var hs = HarmonicSystem.GetHarmonicSystem(harmonicOrder); var harModality = new HarmonicModality(hs, modNumber) { Name = modName }; return harModality; } #endregion #region Public methods /// Clone object. /// Returns value. public override object Clone() { var hm = GetNewHarmonicModality(this.GSystem, this.GetStructuralCode); hm.CopyProperties(this.Properties); return hm; } #endregion #region Properties /// Evaluate properties of the structure. public override void DetermineBehavior() { this.ComputeVariance(); this.ComputeBalance(); var fs = new HarmonicStateFormal((HarmonicSystem)this.GSystem, this); this.Properties[GenProperty.InnerContinuity] = fs.FormalContinuity; this.Properties[GenProperty.InnerImpulse] = fs.FormalImpulse; this.Properties[GenProperty.Consonance] = fs.FormalConsonance; } /// Sets properties of the modality with regard to other modality. /// Abstract modality. public void DetermineBehaviorAfterModality(BinarySchema modality) { if (modality == null) { return; } var harmonicSystem = (HarmonicSystem)this.GSystem; var harRelation = new HarmonicRelation(harmonicSystem, modality, this); var continuity = harRelation.MeanValueOfProperty(GenProperty.InnerContinuity, true, true); var impulse = harRelation.MeanValueOfProperty(GenProperty.InnerImpulse, false, true); var power = (100.0f + impulse - continuity) / 2; this.HarmonicModulationPower = power; } #endregion #region Potential /// Compute formal potential of given element. /// Requested element. /// Returns value. public float PotentialOfElement(byte element) { var hs = new HarmonicStateFormal((HarmonicSystem)this.GSystem, this); hs.AddIntervalsLeadingToElement(element); var p = hs.MeanValueOfProperty(GenProperty.FormalPotentialInfluence, false, true); return p; } #endregion #region Substructures /// /// Harmonic substructures. /// /// General Qualifier. /// Upper limit. /// Returns value. public Collection Substructures(GeneralQualifier genQualifier, int limit) { var hv = StructuralVarietyFactory.NewHarmonicStructModalVariety( StructuralVarietyType.BinarySubstructuresOfModality, this, genQualifier, limit); return hv.StructList; } /// /// Harmonical Substructures. /// /// Returns value. public Collection Substructures() { var hv = StructuralVarietyFactory.NewHarmonicStructModalVariety( StructuralVarietyType.BinarySubstructuresOfModality, this, null, 10000); return hv.StructList; } #endregion #region String representation /// /// Symbols at place. /// /// The given place. /// Returns value. public string SymbolAtPlace(short givenPlace) { var p = givenPlace; var c = this.HarmonicSystem.Symbol(p, true); if (!this.HarmonicSystem.IsEnharmonic(p)) { return c; } var below = (byte)((p + this.Order - 1) % this.Order); var above = (byte)((p + this.Order + 1) % this.Order); var halftoneBelow = this.BitArray[below]; var halftoneAbove = this.BitArray[above]; if (halftoneAbove) { return c; } if (halftoneBelow) { c = this.HarmonicSystem.Symbol(p, false); } else { var down2 = (byte)((p + this.Order - 2) % this.Order); var down3 = (byte)((p + this.Order - 3) % this.Order); var toneDown2 = this.BitArray[down2]; var toneDown3 = this.BitArray[down3]; if (toneDown2 && toneDown3) { c = this.HarmonicSystem.Symbol(p, false); } } return c; } /// /// Returns symbols for given level. /// /// Given level. /// /// Returns value. /// public string SymbolAtLevel(short givenLevel) { var p = this.RealPlaceAtLevel(givenLevel); var c = this.SymbolAtPlace(p); return c; } /// /// Makes tone representation of the structure. /// /// /// Returns value. /// public string SchemaOfTones() { if (this.Level <= 0) { return string.Empty; } var str = new StringBuilder(); var lastL = (byte)(this.Level - 1); string s; for (byte level = 0; level < lastL; level++) { s = this.SymbolAtLevel(level); //// this.PlaceAtLevel str.Append(s); str.Append("-"); } s = this.SymbolAtLevel(lastL); //// this.PlaceAtLevel str.Append(s); return str.ToString().Trim(); } /// Writes particular formal potentials to string. /// Returns value. public string PotentialString() { var s = new StringBuilder(); foreach (var e in this.Places) { var p = this.PotentialOfElement(e); s.AppendFormat(CultureInfo.CurrentCulture, "{0,4}: ", this.SymbolAtPlace(e)); s.AppendFormat(CultureInfo.CurrentCulture, "{0,4:F1}", p); s.Append(Environment.NewLine); } return s.ToString(); } /// String representation of the object. /// Returns value. public override string ToString() { var s = new StringBuilder(); //// s.AppendLine("Harmonic modality"); //// s.AppendLine(base.ToString()); s.Append(this.ToneSchema); //// [s appendFormat:@"%@\n",[[self potentialValues] description]]; //// [s appendFormat:@"%@\n",[[self harFunctions] description]]; return s.ToString(); } #endregion //// Potentials of given harmonic structure /// Compute formal potentials of given harmonic structure. /// Harmonic structure. /// Returns value. private Collection PotentialsForHarmonicStructure(BinarySchema structure) { Contract.Requires(structure != null); var places = structure.Places; var arr = new Collection(); ////struct.Level float potentialSum = 0; foreach (var p in places.Select(this.PotentialOfElement)) { arr.Add(p); potentialSum = potentialSum + p; } #pragma warning disable 168 var i = 0; //// ReSharper disable once UnusedVariable foreach (var e in places.Where(e => potentialSum >= DefaultValue.AfterZero && potentialSum <= DefaultValue.LargeNumber)) { if (i < arr.Count) { arr[i] = arr[i] / potentialSum * 100.0f; } i++; } return arr; } } }